package wechat.forward;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.ActionProvider;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.google.gson.Gson;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import wechat.forward.Helper.WechatMainDBHelper;
import wechat.forward.Model.FriendModel;
import wechat.forward.Model.FriendsAndGroupsModel;
import wechat.forward.Model.ReceiverModel;
import wechat.forward.Model.SettingModel;
import wechat.forward.Util.FileUtil;
import wechat.forward.Util.MainFloatUtil;

import static de.robv.android.xposed.XposedHelpers.callMethod;
import static de.robv.android.xposed.XposedHelpers.callStaticMethod;
import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;
import static de.robv.android.xposed.XposedHelpers.getIntField;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
import static de.robv.android.xposed.XposedHelpers.newInstance;
import static de.robv.android.xposed.XposedHelpers.setObjectField;

/**
 * Created by xuxingcan on 16-11-20.
 */
@SuppressWarnings("ResourceType")
public class XposedInit implements IXposedHookLoadPackage {
    private WechatPackageNames mWechatPackageNames = new WechatPackageNames();
    public static String pkgName = "wechat.forward";
    private static final String fuckSelectedCard = "已选择的群和用户";
    private static final String fuckDelecteUser = "fuckDelecteUser";
    private static final String fuckVideoCompressUI = "fuckVideoCompressUI";
    private static final String fuckSelectedGroup = "fuckSelectedGroup";
    private static final String fuckSelectedFriend = "fuckSelectedFriend";
    private WechatMainDBHelper mDb;
    private Class<?> mModelClass;
    private Class<?> mModelVoiceF;
    private Class<?> mModelVoiceQ;
    private XReceiver mXReceiver;
    private Activity mUIActivity;
    private Class<?> mModelVoiceM;
    private Class<?> mModelMultiClassh;
    private Handler mHandler;
    private Class<?> mUserIdClass;
    private Class<?> mFavoriteClass;
    private Class<?> mPlatformtoolsBBClass;
    private Class<?> mCardSdkClass;
    private Class<?> mModelMClass;
    private Class<?> mStorageAcClass;
    private Object mStorageAc;
    private boolean isForwardVideo = false;
    private static final int requestCodeUploadVideoSns = 401;
    private MainFloatUtil mainFloatUtil;

    public WechatMainDBHelper getWechatMainDBHelper() {
        return mDb;
    }

    @Override
    public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if (!loadPackageParam.packageName.contains("com.tencent.mm")) {
            return;
        }
        mHandler = new Handler(Looper.getMainLooper());
        final ClassLoader loader = loadPackageParam.classLoader;
        try {
            hookDatabase(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookLauncherUI(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookDbObject(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookCard(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookNormalUserFooterPreference(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookVideoForward(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookSelectFriend(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            hookSelectGroup(loadPackageParam.classLoader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
            findAndHookMethod(mWechatPackageNames.secondDexClass, loadPackageParam.classLoader, mWechatPackageNames.secondDexClassMethod, boolean.class, new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    try {
                        classInit(loadPackageParam.classLoader);
                    } catch (Exception e) {
                        XposedBridge.log(e);
                    }
                    try {
                        hookSendFav(loadPackageParam.classLoader);
                    } catch (Exception e) {
                        XposedBridge.log(e);
                    }
                    try {
                        hookVoiceTime(loadPackageParam.classLoader);
                    } catch (Exception e) {
                        XposedBridge.log(e);
                    }
                }
            });
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {
//            hookAllLog(loadPackageParam.classLoader);
//            hookLog(loadPackageParam.classLoader, "MicroMsg.SayHiWithSnsPermissionUI");
//            hookActivity(loader);
        } catch (Exception e) {
            XposedBridge.log(e);
        }
        try {

        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    public void startGroupSelectUI() {
        Intent intent = new Intent();
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.ui.contact.GroupCardSelectUI");
        intent.putExtra("group_select_type", true);
        intent.putExtra("group_select_need_result", false);
        intent.putExtra("group_multi_select", true);
        intent.putExtra(fuckSelectedGroup, true);
        intent.putExtra("max_limit_num", 10000);
        String already_select_contact = "";
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        if (settingModel.selectedGroups != null) {
            for (int i = 0; i < settingModel.selectedGroups.size(); i++) {
                String id = settingModel.selectedGroups.get(i);
                if (i == settingModel.selectedGroups.size() - 1) {
                    already_select_contact += id;
                } else {
                    already_select_contact += id + ",";
                }
            }
        }
        if (!TextUtils.isEmpty(already_select_contact)) {
            intent.putExtra("already_select_contact", already_select_contact);
        }
        mUIActivity.startActivity(intent);
    }

    protected void hookSelectGroup(final ClassLoader loader) {
        findAndHookMethod("com.tencent.mm.ui.MMActivity", loader, "a", int.class, String.class, MenuItem.OnMenuItemClickListener.class, int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                final Activity activity = (Activity) param.thisObject;
                if (activity.getIntent().getBooleanExtra(fuckSelectedGroup, false)) {
                    MenuItem.OnMenuItemClickListener listener = new MenuItem.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem menuItem) {
                            try {
                                List list = (List) getObjectField(activity, mWechatPackageNames.ListObjectInGroupCardSelectUI);
                                SettingModel settingModel = FileUtil.getInstance().getSettingModel();
                                if (settingModel.selectedGroups == null) {
                                    settingModel.selectedGroups = new ArrayList<String>();
                                }
                                settingModel.selectedGroups.clear();
                                for (Object o : list) {
                                    XposedBridge.log(o.toString());
                                    settingModel.selectedGroups.add(o.toString());
                                }
                                FileUtil.getInstance().writeSetting(settingModel);
                                activity.finish();
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                            return false;
                        }
                    };
                    param.args[2] = listener;
                }
            }
        });
        findAndHookMethod("com.tencent.mm.ui.contact.GroupCardSelectUI", loader, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                final Activity activity = (Activity) param.thisObject;
                if (activity.getIntent().getBooleanExtra(fuckSelectedGroup, false)) {
                    ListView listView = (ListView) getObjectField(activity, mWechatPackageNames.ListViewInGroupCardSelectUI);
                    Context pkgContext = activity.createPackageContext(XposedInit.pkgName, Context.CONTEXT_IGNORE_SECURITY);
                    View view = LayoutInflater.from(activity).inflate(pkgContext.getResources().getLayout(R.layout.group_select_head_view_select_all), null);
                    view.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            try {
                                List hvW = (List) getObjectField(activity, mWechatPackageNames.ListWInGroupCardSelectUI);
                                List pkW = (List) getObjectField(activity, mWechatPackageNames.ListObjectInGroupCardSelectUI);
                                if (pkW == null) {
                                    pkW = new ArrayList();
                                } else {
                                    pkW.clear();
                                }
                                for (Object o : hvW) {
                                    pkW.add(getObjectField(o, "field_username"));
                                }
                                callMethod(getObjectField(activity, mWechatPackageNames.AdapterInGroupCardSelectUI), "notifyDataSetChanged");
                                callMethod(activity, mWechatPackageNames.CleanMethodInGroupCardSelectUI);
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                        }
                    });
                    listView.addHeaderView(view);
                    view = LayoutInflater.from(activity).inflate(pkgContext.getResources().getLayout(R.layout.group_select_head_view_cancle_all), null);
                    view.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            try {
                                List list = (List) getObjectField(activity, mWechatPackageNames.ListObjectInGroupCardSelectUI);
                                if (list != null) {
                                    list.clear();
                                }
                                callMethod(getObjectField(activity, mWechatPackageNames.AdapterInGroupCardSelectUI), "notifyDataSetChanged");
                                callMethod(activity, mWechatPackageNames.CleanMethodInGroupCardSelectUI);
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                        }
                    });
                    listView.addHeaderView(view);

                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                            XposedBridge.log("onItemClick");
                            try {
                                if (i - 2 >= 0) {
                                    i = i - 2;
                                    Object wVar = callMethod(getObjectField(activity, mWechatPackageNames.AdapterInGroupCardSelectUI), "getItem", i);
                                    if (wVar == null) {
                                        return;
                                    }
                                    callStaticMethod(activity.getClass(), mWechatPackageNames.StaticClickMethodInGroupCardSelectUI, activity, wVar);
                                    callMethod(activity, mWechatPackageNames.CleanMethodInGroupCardSelectUI);
                                }
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                        }
                    });
                }
            }
        });
    }

    public void startSelectFriend() {
        Intent intent = new Intent();
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.ui.contact.SelectContactUI");
        intent.putExtra("list_attr", 4951);
        intent.putExtra("list_type", 0);
        intent.putExtra(fuckSelectedFriend, true);
        intent.putExtra("scene", 7);
        intent.putExtra("titile", "选择联系人");
        String already_select_contact = "";
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        if (settingModel.selectedFriends != null) {
            for (int i = 0; i < settingModel.selectedFriends.size(); i++) {
                String id = settingModel.selectedFriends.get(i);
                if (i == settingModel.selectedFriends.size() - 1) {
                    already_select_contact += id;
                } else {
                    already_select_contact += id + ",";
                }
            }
        }
        if (!TextUtils.isEmpty(already_select_contact)) {
            intent.putExtra("already_select_contact", already_select_contact);
        }
        mUIActivity.startActivity(intent);
    }

    protected void hookSelectFriend(final ClassLoader loader) {
        findAndHookMethod("com.tencent.mm.ui.MMActivity", loader, "a", int.class, String.class, MenuItem.OnMenuItemClickListener.class, int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                final Activity activity = (Activity) param.thisObject;
                if (activity.getIntent().getBooleanExtra(fuckSelectedFriend, false)) {
                    MenuItem.OnMenuItemClickListener listener = new MenuItem.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem menuItem) {
                            try {
                                HashSet hashSet = (HashSet) getObjectField(activity, mWechatPackageNames.HashSetInSelectContactUI);
                                SettingModel settingModel = FileUtil.getInstance().getSettingModel();
                                if (settingModel.selectedFriends == null) {
                                    settingModel.selectedFriends = new ArrayList<String>();
                                }
                                settingModel.selectedFriends.clear();
                                for (Object o : hashSet) {
                                    XposedBridge.log(o.toString());
                                    settingModel.selectedFriends.add(o.toString());
                                }
                                FileUtil.getInstance().writeSetting(settingModel);
                                activity.finish();
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                            return false;
                        }
                    };
                    param.args[2] = listener;
                }
            }
        });
        findAndHookMethod("com.tencent.mm.ui.MMActivity", loader, "Y", int.class, boolean.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                final Activity activity = (Activity) param.thisObject;
                if (activity.getIntent().getBooleanExtra(fuckSelectedFriend, false)) {
                    param.args[1] = true;
                }
            }
        });
        findAndHookMethod("com.tencent.mm.ui.contact.SelectContactUI", loader, "a", ListView.class, View.OnClickListener.class, String.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        final Activity activity = (Activity) param.thisObject;
                        if (activity.getIntent().getBooleanExtra(fuckSelectedFriend, false)) {
//                            View topView = activity.findViewById(2131755211);
//                            if (topView != null) {
//                                topView.setVisibility(View.GONE);
//                            }
                            if ("选择一个群".equals(param.args[2])) {
                                param.args[2] = "全部选择";
                                param.args[1] = new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        try {
                                            HashSet hashSet = (HashSet) getObjectField(activity, mWechatPackageNames.HashSetInSelectContactUI);
                                            SparseArray array = (SparseArray) getObjectField(
                                                    callMethod(activity, mWechatPackageNames.GetAdapterMethodInSelectContactUI),
                                                    mWechatPackageNames.AdapterSparseArrayInSelectContactUI);
                                            for (int i = 0; i < array.size(); i++) {
                                                Object o = array.get(i);
                                                if (o == null) {
                                                    continue;
                                                }
                                                Object eBw = getObjectField(o, mWechatPackageNames.AdapterSparseArrayItemInSelectContactUI);
                                                if (eBw == null) {
                                                    continue;
                                                }
                                                String userid = (String) getObjectField(eBw, "field_username");
                                                if (userid == null) {
                                                    continue;
                                                }
                                                if (!hashSet.contains(userid)) {
                                                    hashSet.add(userid);
                                                }
                                            }
                                            callMethod(callMethod(activity, mWechatPackageNames.GetAdapterMethodInSelectContactUI), "notifyDataSetChanged");
                                            callMethod(getObjectField(activity, mWechatPackageNames.AdapterFiledInSelectContactUI), "notifyDataSetChanged");
                                            callMethod(activity, mWechatPackageNames.CleanMethodInSelectContactUI);
                                        } catch (Exception e) {
                                            XposedBridge.log(e);
                                        }
                                    }
                                };
                            } else if ("面对面建群".equals(param.args[2])) {
                                param.args[2] = "全部取消";
                                param.args[1] = new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        try {
                                            HashSet hashSet = (HashSet) getObjectField(activity, mWechatPackageNames.HashSetInSelectContactUI);
                                            hashSet.clear();
                                            callMethod(callMethod(activity, mWechatPackageNames.GetAdapterMethodInSelectContactUI), "notifyDataSetChanged");
                                            callMethod(getObjectField(activity, mWechatPackageNames.AdapterFiledInSelectContactUI), "notifyDataSetChanged");
                                            callMethod(activity, mWechatPackageNames.CleanMethodInSelectContactUI);
                                        } catch (Exception e) {
                                            XposedBridge.log(e);
                                        }
                                    }
                                };
                            }
                        }
                    }
                }

        );
    }

    private void startVideoCompressUI(String path) {
        Intent intent = new Intent();
        intent.putExtra(fuckVideoCompressUI, true);
        intent.putExtra("K_SEGMENTVIDEOPATH", path);
        intent.putExtra("KSEGMENTVIDEOTHUMBPATH", "");
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.plugin.mmsight.segment.VideoCompressUI");
        mUIActivity.startActivityForResult(intent, requestCodeUploadVideoSns);
    }

    private void hookVideoForward(final ClassLoader loader) {
        findAndHookMethod(mWechatPackageNames.ImageGalleryUIPopTextClass, loader, mWechatPackageNames.ImageGalleryUIPopTextMethod,
                findClass(mWechatPackageNames.ImageGalleryUIPopTextMethodPar, loader), new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        CharSequence s = "转发至朋友圈";
                        callMethod(param.args[0], mWechatPackageNames.ImageGalleryUIPopTextMethodParMethod, 111, s);
                    }
                });
        findAndHookMethod(mWechatPackageNames.ImageGalleryUIPopTextClickClass, loader, mWechatPackageNames.ImageGalleryUIPopTextClickClassMethod,
                MenuItem.class, int.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        super.beforeHookedMethod(param);
                        MenuItem menuItem = (MenuItem) param.args[0];
                        switch (menuItem.getItemId()) {
                            case 111:
                                isForwardVideo = true;
                                param.args[0] = new MenuItem() {
                                    @Override
                                    public int getItemId() {
                                        return 1;
                                    }

                                    @Override
                                    public int getGroupId() {
                                        return 0;
                                    }

                                    @Override
                                    public int getOrder() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setTitle(CharSequence charSequence) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setTitle(int i) {
                                        return null;
                                    }

                                    @Override
                                    public CharSequence getTitle() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setTitleCondensed(CharSequence charSequence) {
                                        return null;
                                    }

                                    @Override
                                    public CharSequence getTitleCondensed() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIcon(Drawable drawable) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIcon(int i) {
                                        return null;
                                    }

                                    @Override
                                    public Drawable getIcon() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIntent(Intent intent) {
                                        return null;
                                    }

                                    @Override
                                    public Intent getIntent() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setShortcut(char c, char c1) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setNumericShortcut(char c) {
                                        return null;
                                    }

                                    @Override
                                    public char getNumericShortcut() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setAlphabeticShortcut(char c) {
                                        return null;
                                    }

                                    @Override
                                    public char getAlphabeticShortcut() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setCheckable(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isCheckable() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setChecked(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setVisible(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isVisible() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setEnabled(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isEnabled() {
                                        return false;
                                    }

                                    @Override
                                    public boolean hasSubMenu() {
                                        return false;
                                    }

                                    @Override
                                    public SubMenu getSubMenu() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {
                                        return null;
                                    }

                                    @Override
                                    public ContextMenu.ContextMenuInfo getMenuInfo() {
                                        return null;
                                    }

                                    @Override
                                    public void setShowAsAction(int i) {

                                    }

                                    @Override
                                    public MenuItem setShowAsActionFlags(int i) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionView(View view) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionView(int i) {
                                        return null;
                                    }

                                    @Override
                                    public View getActionView() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionProvider(ActionProvider actionProvider) {
                                        return null;
                                    }

                                    @Override
                                    public ActionProvider getActionProvider() {
                                        return null;
                                    }

                                    @Override
                                    public boolean expandActionView() {
                                        return false;
                                    }

                                    @Override
                                    public boolean collapseActionView() {
                                        return false;
                                    }

                                    @Override
                                    public boolean isActionViewExpanded() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setOnActionExpandListener(OnActionExpandListener onActionExpandListener) {
                                        return null;
                                    }
                                };
                                break;
                        }
                    }
                });
        findAndHookMethod(mWechatPackageNames.SnsOnlineVideoActivityPopTextClass, loader, mWechatPackageNames.SnsOnlineVideoActivityPopTextClassMethod,
                ContextMenu.class, View.class, ContextMenu.ContextMenuInfo.class, new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        ContextMenu contextMenu = (ContextMenu) param.args[0];
                        int maxOrder = -1;
                        for (int i = 0; i < contextMenu.size(); i++) {
                            MenuItem item = contextMenu.getItem(i);
                            if (maxOrder < item.getOrder()) {
                                maxOrder = item.getOrder();
                            }
                        }
                        contextMenu.add(0, 111, maxOrder + 1, "转发至朋友圈");
                    }
                });
        findAndHookMethod(mWechatPackageNames.SnsOnlineVideoActivityPopTextClickClass, loader, mWechatPackageNames.SnsOnlineVideoActivityPopTextClickClassMethod,
                MenuItem.class, int.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        super.beforeHookedMethod(param);
                        MenuItem menuItem = (MenuItem) param.args[0];
                        switch (menuItem.getItemId()) {
                            case 111:
                                isForwardVideo = true;
                                param.args[0] = new MenuItem() {
                                    @Override
                                    public int getItemId() {
                                        return 5;
                                    }

                                    @Override
                                    public int getGroupId() {
                                        return 0;
                                    }

                                    @Override
                                    public int getOrder() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setTitle(CharSequence charSequence) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setTitle(int i) {
                                        return null;
                                    }

                                    @Override
                                    public CharSequence getTitle() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setTitleCondensed(CharSequence charSequence) {
                                        return null;
                                    }

                                    @Override
                                    public CharSequence getTitleCondensed() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIcon(Drawable drawable) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIcon(int i) {
                                        return null;
                                    }

                                    @Override
                                    public Drawable getIcon() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setIntent(Intent intent) {
                                        return null;
                                    }

                                    @Override
                                    public Intent getIntent() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setShortcut(char c, char c1) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setNumericShortcut(char c) {
                                        return null;
                                    }

                                    @Override
                                    public char getNumericShortcut() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setAlphabeticShortcut(char c) {
                                        return null;
                                    }

                                    @Override
                                    public char getAlphabeticShortcut() {
                                        return 0;
                                    }

                                    @Override
                                    public MenuItem setCheckable(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isCheckable() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setChecked(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setVisible(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isVisible() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setEnabled(boolean b) {
                                        return null;
                                    }

                                    @Override
                                    public boolean isEnabled() {
                                        return false;
                                    }

                                    @Override
                                    public boolean hasSubMenu() {
                                        return false;
                                    }

                                    @Override
                                    public SubMenu getSubMenu() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {
                                        return null;
                                    }

                                    @Override
                                    public ContextMenu.ContextMenuInfo getMenuInfo() {
                                        return null;
                                    }

                                    @Override
                                    public void setShowAsAction(int i) {

                                    }

                                    @Override
                                    public MenuItem setShowAsActionFlags(int i) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionView(View view) {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionView(int i) {
                                        return null;
                                    }

                                    @Override
                                    public View getActionView() {
                                        return null;
                                    }

                                    @Override
                                    public MenuItem setActionProvider(ActionProvider actionProvider) {
                                        return null;
                                    }

                                    @Override
                                    public ActionProvider getActionProvider() {
                                        return null;
                                    }

                                    @Override
                                    public boolean expandActionView() {
                                        return false;
                                    }

                                    @Override
                                    public boolean collapseActionView() {
                                        return false;
                                    }

                                    @Override
                                    public boolean isActionViewExpanded() {
                                        return false;
                                    }

                                    @Override
                                    public MenuItem setOnActionExpandListener(OnActionExpandListener onActionExpandListener) {
                                        return null;
                                    }
                                };
                                break;
                        }
                    }
                });
        findAndHookMethod("android.widget.Toast", loader, "makeText", Context.class, CharSequence.class, int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                String s = param.args[1].toString();
                if (s.startsWith("视频已保存至") && isForwardVideo) {
                    isForwardVideo = false;
                    param.args[1] = "转发中,请稍后...";
                    String path = s.replaceAll("视频已保存至", "");
                    startVideoCompressUI(path);
                }
            }
        });
        findAndHookMethod("android.app.Activity", loader, "setResult", int.class, Intent.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                if (param.thisObject.getClass().getName().equalsIgnoreCase("com.tencent.mm.plugin.mmsight.segment.VideoCompressUI")) {
                    Activity mActivity = (Activity) param.thisObject;
                    if (mActivity.getIntent().getBooleanExtra(fuckVideoCompressUI, false)) {
                        Intent resultIntent = (Intent) param.args[1];
                        //不是主进程
//                        XposedBridge.log("getExtras = " + resultIntent.getExtras());
//                        XposedBridge.log("System.currentTimeMillis = " + System.currentTimeMillis());
                        Intent intent = new Intent();
                        intent.putExtra("KTouchCameraTime", System.currentTimeMillis() / 1000);
                        intent.putExtra("Ksnsupload_type", 14);
                        intent.putExtra("sight_md5", FileUtil.getFileMD5(new File(resultIntent.getStringExtra("K_SEGMENTVIDEOPATH"))));
                        intent.putExtra("KSightPath", resultIntent.getStringExtra("K_SEGMENTVIDEOPATH"));
                        intent.putExtra("KSightThumbPath", resultIntent.getStringExtra("KSEGMENTVIDEOTHUMBPATH"));
                        intent.putExtra("KSnsPostManu", true);
                        intent.setClassName(mActivity.getPackageName(), mWechatPackageNames.SnsUploadVideoActivity);
                        mActivity.startActivity(intent);
                    }
                }
            }
        });
    }

    private void deleteUser(String userId) {
        Intent intent = new Intent();
        intent.putExtra(fuckDelecteUser, true);
        intent.putExtra("Contact_User", userId);
        intent.putExtra("Contact_Mobile_MD5", "");
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.plugin.profile.ui.ContactInfoUI");
        mUIActivity.startActivity(intent);
    }

    private void hookNormalUserFooterPreference(final ClassLoader loader) {
        findAndHookMethod(mWechatPackageNames.NormalUserFooterPreference, loader, mWechatPackageNames.NormalUserFooterPreferenceInit, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(final MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                Activity mActivity = (Activity) getObjectField(param.thisObject, mWechatPackageNames.NormalUserFooterPreferenceActivity);
                Intent mIntent = mActivity.getIntent();
                if (mIntent != null && mIntent.getBooleanExtra(fuckDelecteUser, false)) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                callMethod(getObjectField(param.thisObject, mWechatPackageNames.NormalUserFooterPreferenceDeleteObject), mWechatPackageNames.NormalUserFooterPreferenceDeleteMethod);
                            } catch (Exception e) {
                                XposedBridge.log(e);
                            }
                        }
                    }, 1000);
                }
            }
        });
    }

    private void hookVoiceTime(final ClassLoader loader) {
        findAndHookMethod(mWechatPackageNames.voiceTimeCallBackClass0, loader, mWechatPackageNames.voiceTimeCallBackClassMethod0, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                long time = (long) param.getResult();
//                XposedBridge.log("time = " + time);
                if (time > 49 * 1000) {
                    if (time - 170 * 1000 > 0) {
                        param.setResult(time - 120 * 1000);
                    } else {
                        param.setResult(49 * 1000);
                    }
                }
            }
        });
        findAndHookMethod(mWechatPackageNames.voiceTimeCallBackClass1, loader, mWechatPackageNames.voiceTimeCallBackClassMethod1, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                long time = (long) param.getResult();
//                XposedBridge.log("time = " + time);
                if (time > 49 * 1000) {
                    if (time - 170 * 1000 > 0) {
                        param.setResult(time - 120 * 1000);
                    } else {
                        param.setResult(49 * 1000);
                    }
                }
            }
        });
        findAndHookMethod(mWechatPackageNames.setVoiceTimeClass, loader, mWechatPackageNames.setVoiceTimeClassMethod, int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                int time = (int) param.args[0];
                param.args[0] = 190000;
            }
        });
        findAndHookMethod(mModelVoiceQ, mWechatPackageNames.forwarderVoiceMethod, String.class, int.class, int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                int time = (int) param.args[1];
//                XposedBridge.log("origin Time = " + time);
                if (time > 60000 || time == -1) {
                    time = (int) (Math.random() * 50000) + 10000;
//                    XposedBridge.log("set Time = " + time);
                    param.args[1] = time;
                }
            }
        });
        findAndHookMethod(mModelVoiceF, mWechatPackageNames.mModelVoiceFTimeMethod, new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                return 180;
            }
        });
        findAndHookMethod(mModelVoiceF, mWechatPackageNames.mModelVoiceFReportMethod, int.class, int.class, int.class, String.class, findClass("com.tencent.mm.network.p", loader), byte[].class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                int i = (int) param.args[0];
                int i2 = (int) param.args[1];
                int i3 = (int) param.args[2];
                if (i2 == 4 && i3 == -2) {
                    param.args[1] = 0;
                    param.args[2] = 0;
                }
            }
        });
    }

    protected void hookDbObject(final ClassLoader loader) {
        findAndHookConstructor(mWechatPackageNames.storageClass, loader, mWechatPackageNames.storageClassInitParam, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                if (mDb == null) {
                    try {
                        mDb = new WechatMainDBHelper(param.args[0]);
                        mStorageAcClass = findClass(mWechatPackageNames.StorageAcClass, loader);
                        mStorageAc = newInstance(mStorageAcClass, param.args[0]);
                    } catch (Throwable t) {
                    }
                }
            }
        });
    }

    protected void hookDatabase(final ClassLoader loader) {
        XposedHelpers.findAndHookMethod(mWechatPackageNames.datebaseClass, loader,
                mWechatPackageNames.datebaseClassMethod, String.class, String.class, ContentValues.class, int.class, new XC_MethodHook() {

                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        String s = (String) param.args[0];
                        if (!s.equalsIgnoreCase("message")) {
                            return;
                        }
                        ContentValues v = (ContentValues) param.args[2];
                        for (String key : v.keySet()) {
                            Object object = v.get(key);
                            if (object == null) {
                                XposedBridge.log(key + " = null");
                            } else {
                                XposedBridge.log(key + " = " + object.toString() + "   " + object.getClass().getName());
                            }
                        }
                        final String talker = v.getAsString("talker");
                        String content = v.getAsString("content");
                        int isSend;
                        if (v.containsKey("isSend")) {
                            isSend = v.getAsInteger("isSend");
                        } else {
                            isSend = content.startsWith(getUserId()) ? 1 : 0;
                        }
                        int type = v.getAsInteger("type");
//                        int status = v.getAsInteger("status");
//                        if (status == 1) {
//                            v.put("status", 5);
//                        }
                        if (isSend == 1) {
                            switch (type) {
                                case 1:
                                    break;
                                case 436207665:
                                    break;
                                case 34://语音
                                    final String voicePath = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoicePathMethod, v.getAsString("imgPath"));
//                                    XposedBridge.log("voicePath = " + voicePath);
//                                    XposedBridge.log("content = " + content);
                                    String[] cs = content.split(":");
                                    int voiceTime = Integer.parseInt(cs[1]);
                                    if (voiceTime == -1 || voiceTime == 49000) {
                                        int time = (int) (Math.random() * 50000) + 10000;
                                        if (time == 49000) {
                                            time = 52778;
                                        }
                                        param.args[0] = "";
                                        param.args[1] = "";
                                        param.args[2] = new ContentValues();
                                        String newVoiceNumber = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoiceNumberMethod, talker);
                                        String imgPath = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoicePathMethod, newVoiceNumber);
                                        if (copyFile(new File(voicePath), new File(imgPath))) {
                                            XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.forwarderVoiceMethod, newVoiceNumber, time, 1);
                                            sendVoice(imgPath);
                                        }
                                        mHandler.postDelayed(new Runnable() {
                                            @Override
                                            public void run() {
                                                XposedHelpers.callMethod(XposedHelpers.callStaticMethod(mModelVoiceM, mWechatPackageNames.refreshSendStatusMethod), "run");
                                            }
                                        }, 3000L);
                                    } else if ("filehelper".equalsIgnoreCase(talker)) {
                                        doSomeSendVoice(voicePath, voiceTime);
                                    }
                                    break;
                                case 3://图片
                                    break;
                                case 62://小视频
                                    break;
                                case 10000:
                                    break;
                            }
                        } else {
                            switch (type) {
                                case 1:
                                    break;
                                case 436207665:
                                    break;
                                case 34://语音
                                    break;
                                case 3://图片
                                    break;
                                case 62://小视频
                                    break;
                                case 10000:
                                    if (content.contains("weixin://findfriend/verifycontact")) {
                                        deleteUser(talker);
                                    }
                                    break;
                            }
                        }
                    }
                });
    }

    public static boolean copyFile(final File rawFile, final File newFile) {
        try {
            if (!rawFile.exists()) {
                return false;
            }
            final BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(rawFile));
            final byte[] array = new byte[bufferedInputStream.available()];
            bufferedInputStream.read(array);
            bufferedInputStream.close();
            if (!newFile.exists()) {
                newFile.createNewFile();
            }
            final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newFile));
            bufferedOutputStream.write(array);
            bufferedOutputStream.flush();
            bufferedOutputStream.close();
            return true;
        } catch (Throwable t) {
            return false;
        }
    }

    public void sendVoice(String path) {
        XposedHelpers.callMethod(XposedHelpers.callStaticMethod(this.mModelClass, mWechatPackageNames.statusSendMethod),
                mWechatPackageNames.sendMethod, XposedHelpers.newInstance(this.mModelVoiceF, new Object[]{path}), 0);
    }

    public void sendText(String to, String content) {
        XposedHelpers.callMethod(XposedHelpers.callStaticMethod(this.mModelClass, mWechatPackageNames.statusSendMethod),
                mWechatPackageNames.sendMethod, XposedHelpers.newInstance(this.mModelMultiClassh, new Object[]{to, content, 1}), 0);
    }

    public void ak_vy_a(Object o) {
        XposedHelpers.callMethod(XposedHelpers.callStaticMethod(this.mModelClass, mWechatPackageNames.statusSendMethod),
                mWechatPackageNames.sendMethod, o, 0);
    }

    public String getUserId() {
        return (String) callStaticMethod(mUserIdClass, mWechatPackageNames.getUserIdMethod);
    }

    private void classInit(ClassLoader loader) {
        mModelClass = findClass(mWechatPackageNames.mModleClass, loader);
        mModelVoiceF = findClass(mWechatPackageNames.mModelVoiceF, loader);
        mModelVoiceQ = findClass(mWechatPackageNames.mModelVoiceQ, loader);
        mModelVoiceM = findClass(mWechatPackageNames.mModelVoiceM, loader);
        mModelMultiClassh = findClass(mWechatPackageNames.mModelMultiClassh, loader);
        mUserIdClass = findClass(mWechatPackageNames.mUserIdClass, loader);
        mFavoriteClass = findClass(mWechatPackageNames.mFavoriteClass, loader);
        mPlatformtoolsBBClass = findClass(mWechatPackageNames.mPlatformtoolsBBClass, loader);
        mCardSdkClass = findClass(mWechatPackageNames.cardSdkClass, loader);
        mModelMClass = findClass(mWechatPackageNames.pluginsdkModelM, loader);
    }

    private void hookLauncherUI(ClassLoader loader) {
        findAndHookMethod("com.tencent.mm.ui.LauncherUI", loader, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                mUIActivity = (Activity) param.thisObject;
                mXReceiver = new XReceiver();
                mUIActivity.registerReceiver(mXReceiver, mXReceiver.getIntentFilter());
                mainFloatUtil = new MainFloatUtil((Context) param.thisObject, XposedInit.this);
                mainFloatUtil.createFloatView();
            }
        });
        findAndHookMethod("com.tencent.mm.ui.LauncherUI", loader, "onPause", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                mainFloatUtil.getFloatLayout().setVisibility(View.GONE);
            }
        });
        findAndHookMethod("com.tencent.mm.ui.LauncherUI", loader, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                mainFloatUtil.getFloatLayout().setVisibility(View.VISIBLE);
            }
        });
        findAndHookMethod("com.tencent.mm.ui.LauncherUI", loader, "onDestroy", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                mainFloatUtil.clearFloatView();
                mainFloatUtil = null;
                Context mContext = (Context) param.thisObject;
                if (mXReceiver != null) {
                    mContext.unregisterReceiver(mXReceiver);
                }
            }
        });
    }

    public void startFavSelectUI() {
        Intent intent = new Intent();
        intent.putExtra("key_to_user", fuckSelectedCard);
        intent.putExtra("key_fav_item_id", "3");
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.plugin.favorite.ui.FavSelectUI");
        mUIActivity.startActivity(intent);
    }

    private void hookSendFav(ClassLoader loader) {
        findAndHookMethod(mFavoriteClass, mWechatPackageNames.sendFavClassMethod,
                Context.class, String.class, String.class, List.class, Runnable.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        super.beforeHookedMethod(param);
                        String sendId = (String) param.args[1];
                        XposedBridge.log("id = " + sendId);
                        if (fuckSelectedCard.equalsIgnoreCase(sendId)) {
                            doSomeSendFav(param);
                            param.args[1] = null;
                        }
                    }
                });
    }

    public void sendCard() {
        Intent intent = new Intent();
        intent.setClassName(mUIActivity.getPackageName(), "com.tencent.mm.ui.contact.SelectContactUI");
        intent.putExtra("list_attr", 18454);
        intent.putExtra("list_type", 4);
        intent.putExtra("max_limit_num", 10000);
        intent.putExtra("received_card_name", fuckSelectedCard);
        intent.putExtra("block_contact", fuckSelectedCard);
        intent.putExtra(fuckSelectedCard, true);
        intent.putExtra("Add_SendCard", true);
        intent.putExtra("titile", "选择联系人");
        mUIActivity.startActivity(intent);
    }

    private void hookCard(final ClassLoader loader) {
        findAndHookMethod("com.tencent.mm.ui.contact.SelectContactUI", loader, mWechatPackageNames.onSelectContactUIMethod, List.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                Activity activity = (Activity) param.thisObject;
                if (activity.getIntent().getBooleanExtra(fuckSelectedCard, false)) {
                    String card = (String) callStaticMethod(mPlatformtoolsBBClass, mWechatPackageNames.genSendCardMethod, param.args[0], ",");
                    doSomeSendCard(card);
                }
            }
        });
    }

    private void hookActivity(ClassLoader loader) {
        findAndHookMethod("android.app.Activity", loader, "onActivityResult", int.class, int.class, Intent.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                int requestCode = (int) param.args[0];
                int resultCode = (int) param.args[1];
                Intent mIntent = (Intent) param.args[2];
                XposedBridge.log("requestCode = " + requestCode);
                XposedBridge.log("resultCode = " + resultCode);
                XposedBridge.log("getExtras = " + mIntent.getExtras());
            }
        });
        findAndHookMethod("android.app.Activity", loader, "setResult", int.class, Intent.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                try {
                    throw new Exception("setResult");
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        });
        findAndHookMethod("android.app.Activity", loader, "setResult", int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                try {
                    throw new Exception("setResult");
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        });
        findAndHookMethod("android.app.Activity", loader, "startActivityForResult", Intent.class, int.class, Bundle.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                try {
                    Intent mIntent = (Intent) param.args[0];
                    XposedBridge.log("getExtras = " + mIntent.getExtras());
                    XposedBridge.log("getClassName = " + mIntent.getComponent().getClassName());
                    throw new Exception("startActivityForResult");
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        });
        findAndHookMethod("android.app.Activity", loader, "startActivity", Intent.class, Bundle.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                try {
                    Intent mIntent = (Intent) param.args[0];
                    XposedBridge.log("getExtras = " + mIntent.getExtras());
                    XposedBridge.log("getClassName = " + mIntent.getComponent().getClassName());
                    throw new Exception("startActivity");
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        });
    }

    public static AlertDialog showOnlyMessageDialog(Context mContext, String title, String msg) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);  //先得到构造器
        builder.setTitle(title); //设置标题
        builder.setMessage(msg); //设置内容
        builder.setCancelable(false);
        AlertDialog dialog = builder.create();
        dialog.show();
        return dialog;
    }

    private void doSomeSendFav(final XC_MethodHook.MethodHookParam param) {
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        long intervalTime = settingModel.intervalTime;
        if (intervalTime <= 0) {
            intervalTime = 1;
        }
        long delayTime = 1;
        if (settingModel.selectedGroups != null) {
            for (final String id : settingModel.selectedGroups) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callStaticMethod(mFavoriteClass, mWechatPackageNames.sendFavClassMethod, param.args[0], id, param.args[2], param.args[3], new Runnable() {
                                @Override
                                public void run() {

                                }
                            });
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
        if (settingModel.selectedFriends != null) {
            for (final String id : settingModel.selectedFriends) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callStaticMethod(mFavoriteClass, mWechatPackageNames.sendFavClassMethod, param.args[0], id, param.args[2], param.args[3], new Runnable() {
                                @Override
                                public void run() {

                                }
                            });
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
    }

    private void doSomeSendVoice(final String voicePath, final int voiceTime) {
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        long intervalTime = settingModel.intervalTime;
        if (intervalTime <= 0) {
            intervalTime = 1;
        }
        long delayTime = 1;
        if (settingModel.selectedGroups != null) {
            for (final String id : settingModel.selectedGroups) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String newVoiceNumber = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoiceNumberMethod, id);
                            String imgPath = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoicePathMethod, newVoiceNumber);
                            if (copyFile(new File(voicePath), new File(imgPath))) {
                                XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.forwarderVoiceMethod, newVoiceNumber, voiceTime, 1);
                                sendVoice(imgPath);
                            }
                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    XposedHelpers.callMethod(XposedHelpers.callStaticMethod(mModelVoiceM, mWechatPackageNames.refreshSendStatusMethod), "run");
                                }
                            }, 3000L);
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
        if (settingModel.selectedFriends != null) {
            for (final String id : settingModel.selectedFriends) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String newVoiceNumber = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoiceNumberMethod, id);
                            String imgPath = (String) XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.getVoicePathMethod, newVoiceNumber);
                            if (copyFile(new File(voicePath), new File(imgPath))) {
                                XposedHelpers.callStaticMethod(mModelVoiceQ, mWechatPackageNames.forwarderVoiceMethod, newVoiceNumber, voiceTime, 1);
                                sendVoice(imgPath);
                            }
                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    XposedHelpers.callMethod(XposedHelpers.callStaticMethod(mModelVoiceM, mWechatPackageNames.refreshSendStatusMethod), "run");
                                }
                            }, 3000L);
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
    }

    public void doSomeSendText(final String content) {
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        long intervalTime = settingModel.intervalTime;
        if (intervalTime <= 0) {
            intervalTime = 1;
        }
        long delayTime = 1;
        if (settingModel.selectedGroups != null) {
            for (final String id : settingModel.selectedGroups) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            sendText(id, content);
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
        if (settingModel.selectedFriends != null) {
            for (final String id : settingModel.selectedFriends) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            sendText(id, content);
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
    }

    private void doSomeSendCard(final String card) {
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        long intervalTime = settingModel.intervalTime;
        if (intervalTime <= 0) {
            intervalTime = 1;
        }
        long delayTime = 1;
        if (settingModel.selectedGroups != null) {
            for (final String id : settingModel.selectedGroups) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callMethod(callStaticMethod(mCardSdkClass, mWechatPackageNames.cardSdkSendObject), mWechatPackageNames.cardSdkSendMethod, card, id, id.endsWith("@chatroom"));
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
        if (settingModel.selectedFriends != null) {
            for (final String id : settingModel.selectedFriends) {
                delayTime += intervalTime;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callMethod(callStaticMethod(mCardSdkClass, mWechatPackageNames.cardSdkSendObject), mWechatPackageNames.cardSdkSendMethod, card, id, id.endsWith("@chatroom"));
                        } catch (Exception e) {
                            XposedBridge.log(e);
                        }
                    }
                }, delayTime);
            }
        }
    }

    private void doSomeAddFriends(ArrayList<String> ids, final String chatRoomId, final String text) {
        SettingModel settingModel = FileUtil.getInstance().getSettingModel();
        long intervalTime = settingModel.intervalTime;
        if (intervalTime <= 0) {
            intervalTime = 1;
        }
        long delayTime = 1;
        for (final String id : ids) {
            delayTime += intervalTime;
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    try {
                        List list0 = new ArrayList();
                        list0.add(id);
                        List list1 = new ArrayList();
                        list1.add(14);
                        Map hashMap = new HashMap();
                        hashMap.put(id, 0);
                        Object k = newInstance(mModelMClass, list0, list1, text, "", hashMap, chatRoomId);
                        ak_vy_a(k);
                        XposedBridge.log(id);
                    } catch (Exception e) {
                        XposedBridge.log(e);
                    }
                }
            }, delayTime);
        }
    }

//    public static void findAndHookConstructor(String className, ClassLoader classLoader, Object... parameters) {
//        Class<?> cls = findClass(className, classLoader);
//        Class<?>[] parameterTypes = new Class[parameters.length - 1];
//        for (int i = 0; i < parameters.length - 1; i++) {
//            if (parameters[i] instanceof String) {
//                parameterTypes[i] = findClass((String) parameters[i], classLoader);
//            } else if (parameters[i] instanceof Class) {
//                parameterTypes[i] = (Class<?>) parameters[i];
//            }
//        }
//        try {
//            Constructor<?> constructor = cls.getDeclaredConstructor(parameterTypes);
//            constructor.setAccessible(true);
//            XC_MethodHook callback = (XC_MethodHook) parameters[parameters.length - 1];
//            XposedBridge.hookMethod(constructor, callback);
//        } catch (Throwable t) {
//            XposedBridge.log(t);
//        }
//    }

    public ArrayList<FriendModel> getFriends() {
        ArrayList<FriendModel> list = getWechatMainDBHelper().getFriendsModel();
        for (FriendModel friendModel : list) {
            //c.wF().MF(mi)
            Object o = callMethod(mStorageAc, mWechatPackageNames.StorageAcGetUserModelMethod, friendModel.mainId);
            setObjectField(o, mWechatPackageNames.StorageAcSetUserModelIdMethod, friendModel.mainId);
            friendModel.city = (String) callMethod(o, mWechatPackageNames.StorageAcUserModelGetCityMethod);
            friendModel.province = (String) callMethod(o, mWechatPackageNames.StorageAcUserModelGetProvinceMethod);
            friendModel.sex = getIntField(o, mWechatPackageNames.StorageAcUserModelSexFiled);
        }
        return list;
    }

    private void hookLog(ClassLoader loader, final String tag) {
        String[] strings = new String[]{"i", "d", "e", "v", "w"};
        for (String level : strings) {
            findAndHookMethod(mWechatPackageNames.logClass, loader, level, String.class, String.class, Object[].class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    String s0 = (String) param.args[0];
                    if (!s0.equals(tag)) {
                        return;
                    }
                    String s1 = (String) param.args[1];
                    Object[] objects = (Object[]) param.args[2];
                    if (objects != null && objects.length >= 0) {
                        s1 = String.format(s1, objects);
                    }
                    XposedBridge.log(s0 + "     " + s1);
                }
            });
        }
    }

    private void hookAllLog(ClassLoader loader) {
        String[] strings = new String[]{"i", "d", "e", "v", "w"};
        for (String level : strings) {
            findAndHookMethod(mWechatPackageNames.logClass, loader, level, String.class, String.class, Object[].class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    String s0 = (String) param.args[0];
                    String s1 = (String) param.args[1];
                    Object[] objects = (Object[]) param.args[2];
                    if (objects != null && objects.length >= 0) {
                        s1 = String.format(s1, objects);
                    }
                    XposedBridge.log(s0 + "     " + s1);
                }
            });
        }
    }

    private static Gson gson = new Gson();

    public class XReceiver extends BroadcastReceiver {
        public static final String X_RECEIVER_ACTION = "X_RECEIVER_ACTION";
        public static final String JSON = "JSON";

        public IntentFilter getIntentFilter() {
            IntentFilter mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(X_RECEIVER_ACTION);
            return mIntentFilter;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent == null || intent.getAction() == null) {
                return;
            }
            String action = intent.getAction();
            XposedBridge.log("onReceive = " + action);
            if (action.equalsIgnoreCase(X_RECEIVER_ACTION)) {
                try {
                    ReceiverModel receiverModel = gson.fromJson(intent.getStringExtra(JSON), ReceiverModel.class);
                    switch (receiverModel.type) {
                        case ReceiverModel.REFRESH_SETTING:
                            FileUtil.getInstance().reloadSetting();
                            break;
                        case ReceiverModel.SEND_TEXT:
                            doSomeSendText(receiverModel.text);
                            break;
                        case ReceiverModel.SEND_FAV:
                            startFavSelectUI();
                            break;
                        case ReceiverModel.SEND_CARD:
                            sendCard();
                            break;
                        case ReceiverModel.SAVE_FRIENDS:
                            ArrayList<FriendModel> list = getFriends();
                            FileUtil.writeFileSdcardFile(new File(Environment.getExternalStorageDirectory(), "wechat.forwarder.friend.json"), gson.toJson(list));
                            Toast.makeText(mUIActivity, "已保存至SD卡根目录\n'wechat.forwarder.friend.json'文件", Toast.LENGTH_LONG).show();
                            break;
                        case ReceiverModel.REFRESH_FRIENDS_AND_GROUP:
                            FriendsAndGroupsModel friendsAndGroupsModel = new FriendsAndGroupsModel();
                            friendsAndGroupsModel.friendModelArrayList = getWechatMainDBHelper().getFriendsModel();
                            friendsAndGroupsModel.groupModelArrayList = getWechatMainDBHelper().getGroupsModel();
                            friendsAndGroupsModel.allChatRoomMemberModels = getWechatMainDBHelper().getAllChatRoomMembers();
                            FileUtil.writeFileSdcardFile(new File(Environment.getExternalStorageDirectory(), "wechat.forwarder.friends_and_groups.json"), gson.toJson(friendsAndGroupsModel));
                            sendRefreshFriendsAndGroupDone2MainReceiver();
                            break;
                        case ReceiverModel.ADD_FRIENDS:
                            doSomeAddFriends(receiverModel.list, receiverModel.chatRoomId, receiverModel.text);
                            break;
                    }
                } catch (Exception e) {
                    XposedBridge.log(e);
                }
            }
        }
    }

    private void sendRefreshFriendsAndGroupDone2MainReceiver() {
        ReceiverModel receiverModel = new ReceiverModel();
        receiverModel.type = ReceiverModel.REFRESH_FRIENDS_AND_GROUP_DONE;
        sendReceiverModel2MainReceiver(receiverModel);
    }

    private void sendReceiverModel2MainReceiver(ReceiverModel receiverModel) {
        Intent mIntent = new Intent("MAIN_ACTION");
        mIntent.putExtra("JSON", gson.toJson(receiverModel));
        mUIActivity.sendBroadcast(mIntent);
    }
}
